package org.itboys.shop.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;import java.text.DecimalFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.itboys.basetemplate.service.IncomeRecordService;
import org.itboys.commons.CommonConstants;
import org.itboys.commons.CommonConstants.DF;
import org.itboys.commons.CommonConstants.NUM;
import org.itboys.commons.utils.ajax.AjaxUtils;
import org.itboys.commons.utils.ip.IPUtil;
import org.itboys.commons.utils.random.RandomUtils;
import org.itboys.commons.utils.string.SelfStringUtils;
import org.itboys.commons.utils.tools.ResponseManager;
import org.itboys.framework.spring.controller.BaseController;
import org.itboys.member.entity.Member;
import org.itboys.pay.constant.PayConstants;
import org.itboys.pay.weixin.Unifiedorder;
import org.itboys.pay.weixin.Unifiedorder_bak;
import org.itboys.pay.weixin.WeixinPaySignTool;
import org.itboys.product.entity.Product;
import org.itboys.product.service.ProductService;
import org.itboys.shop.WXConstants;
import org.itboys.shop.dto.order.WXOrderSucDto;
import org.itboys.shop.entity.OrderSellRecord;
import org.itboys.shop.entity.ShopSeller;
import org.itboys.shop.service.OrderSellService;
import org.itboys.shop.service.ShopSellerService;
import org.itboys.shop.tools.WXSession;
import org.itboys.trade.constant.OrderConstant;
import org.itboys.trade.entity.Order;
import org.itboys.trade.entity.OrderItem;
import org.itboys.trade.entity.PrePay;
import org.itboys.trade.entity.TicketOrder;
import org.itboys.trade.entity.mysql.AdminAmountRecord;
import org.itboys.trade.service.OrderItemService;
import org.itboys.trade.service.OrderService;
import org.itboys.trade.service.PrePayService;
import org.itboys.trade.service.TicketOrderService;
import org.itboys.trade.service.mysql.AdminAmountRecordService;
import org.itboys.trade.service.mysql.UserWithdrawRecordService;
import org.itboys.weixin.tools.XMLUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

/**
 * 商品
 * @author 
 *
 */
@RestController
@RequestMapping("/wx/trade")
public class WXTradeController extends BaseController{
	@Autowired
	private PrePayService PrePayService;
	@Autowired
	private OrderService OrderService;
	@Autowired
	private TicketOrderService ticketOrderService;
	@Autowired
	private OrderItemService itemService;
	@Autowired
	private IncomeRecordService incomeRecordService;
	@Autowired
	private ProductService productService;
	@Autowired
	private ShopSellerService sellerService;
	@Autowired
	private OrderSellService orderSellService;
    @Autowired
    private UserWithdrawRecordService withdrawRecordService;
    @Autowired
    private AdminAmountRecordService adminRecordService;
	private HashSet<Long>prepayIds=new HashSet<>();
	private static final String PRO_ORDER="normal";
	private static final String TICKET_ORDER="ticket";
	private static final String pay_type_weixin="wx";
	@RequestMapping("/prepay")
	public ModelAndView prepay(
			@RequestParam Long orderId,
			@RequestParam String orderType,
			Model model,HttpServletRequest request, HttpServletResponse response) {
		try {
			
			Long memberId=WXSession.getMember(request).getId();
			PrePay prePay=new PrePay();
			prePay.setOrderType(orderType);
			prePay.setMemberId(memberId);
			prePay.setOrderId(orderId);
			prePay.setPrepayNo("P"+DF.FORMAT_yyyyMMddHHmmss.format(new Date())+RandomUtils.buildRandom(4));
			switch (orderType) {
			case PRO_ORDER:
				Order order=OrderService.getById(orderId);
				if (!order.getStatus().equals(OrderConstant.WAIT_PAY)) {
					AjaxUtils.renderJson(response, CommonConstants.FAIL);
					return null;
				}
				prePay.setAmount(order.getTotalMoney());
				break;
			case TICKET_ORDER:
				TicketOrder ticketOrder=ticketOrderService.getById(orderId);
				if (ticketOrder.getStatus()!=TicketOrder.status_create) {
					AjaxUtils.renderJson(response, CommonConstants.FAIL);
					return null;
				}
				prePay.setAmount(ticketOrder.getTotalMoney());
				break;
			default:
				break;
			}
			PrePayService.save(prePay);
			model.addAttribute("amount", NUM.DF_00.format(prePay.getAmount()/100d));
			model.addAttribute("prepayNo", prePay.getPrepayNo());
			return new ModelAndView("/order/OrderPay");
		} catch (Exception e) {
			logger.error("",e);
			AjaxUtils.renderJson(response, CommonConstants.FAIL);
			return null;
		}
	}
	
	/**
     * 微信支付
     * @param orderId
     * @param amount
     * @param request
     * @param response
     */
    @RequestMapping("/wxPay")
    public void wxPay(@RequestParam String prepayNo,HttpServletRequest request,HttpServletResponse response) {
        try{
            Member member = WXSession.getMember(request);
//            Member member = memberService.getById(3L);
//            WeixinConfig config = weixinConfigService.getByField("shopId", member.getShopId());
            String appId = WXConstants.appId;
            String mchId = WXConstants.mch;
            String apiSecret = WXConstants.secrit;
            String openId = member.getOpenId();
            String spbillCreateIp = IPUtil.getIpAddr(request);
            if (spbillCreateIp.contains(",")) {
				spbillCreateIp=spbillCreateIp.split(",")[0];
			}
            String tradeType = Unifiedorder.TRADE_TYPE_JS;
//            String prepayNo = prepayNo;

            String notifyUrl = WXConstants.notifyUrl;
            //这里的totalFee=订单的支付金额
            PrePay prePay=PrePayService.getByField("prepayNo", prepayNo);
            if (null==prePay||prePay.getStatus()==PrePay.status_success) {
            	ResponseManager.NullError(response);
				return;
			}
            String totalFeeStr ="1"; //String.valueOf(prePay.getAmount());
            
            Unifiedorder unifiedorder = new Unifiedorder(
                    appId,
                    mchId, 
                    notifyUrl,
                    openId,
                    prepayNo,
                    spbillCreateIp, 
                    tradeType, 
                    "美丽乡村交易号:"+prepayNo, 
                    totalFeeStr, 
                    WXConstants.key);
            logger.info("****************************param************************"+unifiedorder.getXML());
            String result = getprepayId(unifiedorder);  //请求微信生成订单
            logger.info("wxpay result------------------"+result);
            if(StringUtils.isNotBlank(result)){
                Map<String, Object> map = XMLUtil.doXMLParse(result);
                String returnCode = (String)map.get("return_code");
                String resultCode = (String)map.get("result_code");

                if(returnCode.toLowerCase().equals(CommonConstants.SUCCESS) && resultCode.toLowerCase().equals(CommonConstants.SUCCESS)){
                    String prepayId = (String)map.get("prepay_id");
                    WeixinPaySignTool tool = new WeixinPaySignTool(appId, prepayId, WXConstants.key);
                    ResponseManager.normalResult(tool, response);
                    return;
                }else {//统一下单失败
                    String returnMsg = (String)map.get("return_msg");
                    String errCode = (String)map.get("err_code");
                    String errCodeDes = (String)map.get("err_code_des");
                    logger.error(returnMsg+"--"+errCode, errCodeDes);
                    ResponseManager.CustomizedError(response, errCodeDes);
                    return;
                }
            } else {
            	ResponseManager.CustomizedError(response, "下单请求失败");
            }
        }catch(Exception e){
            e.printStackTrace();
            ResponseManager.SystemError(response);
            logger.error(e.getMessage(), e);
        }
    }
    /**
     * 微信支付前的获取的一些必要的信息
     * @param unifiedorder
     * @return
     * @throws IOException
     */
    public static String getprepayId(Unifiedorder unifiedorder) throws IOException{
        String result = null;

        String param = unifiedorder.getXML();
        URL urll = new URL(Unifiedorder.URL);
        HttpURLConnection connection = (HttpURLConnection) urll.openConnection();

        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setUseCaches(false);
        connection.setInstanceFollowRedirects(true);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Accept", "application/string");
        connection.setRequestProperty("Content-Type", "application/xml");
        connection.connect();
        OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");

        out.append(param.toString());
        out.flush();
        out.close();

        int length = connection.getContentLength();
        InputStream is = connection.getInputStream();
        if (length != -1) {
            byte[] data = new byte[length];
            byte[] temp = new byte[512];
            int readLen = 0;
            int destPos = 0;
            while ((readLen = is.read(temp)) > 0) {
                System.arraycopy(temp, 0, data, destPos, readLen);
                destPos += readLen;
            }
            result = new String(data, "UTF-8");
        }
        return result;
    }

	
	@RequestMapping("/WXCallBack")
	public String WXCallBack(
			HttpServletRequest request, HttpServletResponse response) {
		  try {
	            InputStream inStream = request.getInputStream();
	            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
	            byte[] buffer = new byte[1024];
	            int len = 0;
	            while ((len = inStream.read(buffer)) != -1) {
	                outStream.write(buffer, 0, len);
	            }
	            outStream.close();
	            inStream.close();
	            String result = new String(outStream.toByteArray(), "utf-8");
	            Map map = XMLUtil.doXMLParse(result);
	            String returnCode = String.valueOf(map.get("return_code"));
	            String prepayNo = String.valueOf(map.get("out_trade_no"));
	            String nonceStr = String.valueOf(map.get("nonce_str"));   //随机字符串
	            logger.info("returnCode-----"+returnCode+"\n prepayNo-----"+prepayNo+"\n nonceStr-----"+nonceStr);
	            //微信支付订单号
	            String transaction_id = String.valueOf(map.get("transaction_id"));
//	            System.out.println("transaction_id----------------------------------"+transaction_id);
	            //支付成功，修改订单状态
	            return callback(prepayNo,PayConstants.PayWay.WEIXIN,transaction_id, response);
	        } catch (Exception e) {
	            e.printStackTrace();
	            logger.error(e.getMessage(), e);
	            return "FAIL";
	        }
	}

	private String callback(String prepayNo,Integer payType,String thirdTradeNo, HttpServletResponse response) {
		logger.info("start callback prepayNo:"+prepayNo);
		PrePay prePay=PrePayService.getByField("prepayNo", prepayNo);
		prePay.setPayType(payType);
		prePay.setThirdTradeNo(thirdTradeNo);
		OrderSellRecord record=new OrderSellRecord();
		if (prePay.getStatus()==PrePay.status_success) {
			return "SUCESS";
		}
		switch (prePay.getOrderType()) {
		case PRO_ORDER:
			return normalOrderCallBack(response, prePay);
		case TICKET_ORDER:
			return ticketOrderCallBack(response, prePay);
		default:
			return "FAIL";
		}
	}
	private String normalOrderCallBack(HttpServletResponse response, PrePay prePay) {
		Order order=OrderService.getById(prePay.getOrderId());
		if (order.getStatus()>OrderConstant.WAIT_PAY) {
			return "SUCESS";
		}
		if (prepayIds.add(prePay.getId())) {
			order.setPayTime(new Date());
			order.setStatus(OrderConstant.WAIT_SEND);
			OrderService.update(order);
			List<OrderItem>items=itemService.findByField("orderId", order.getId());
			items.forEach(i->{
				
				i.setStatus(OrderConstant.WAIT_SEND);
				Product product=productService.getById(i.getProductId());
				productService.update(i.getProductId(), "soldCount", null==product.getSoldCount()?1:product.getSoldCount()
						+1);
			});
			itemService.batchUpdate(items);
			//分佣
			incomeRecordService.startIncome(order.getId());
			orderSellService.saveRecord(order, prePay);
			prepayIds.remove(prePay.getId());
			prePay.setStatus(PrePay.status_success);
			PrePayService.update(prePay);
			
			
			return "SUCESS";
		}else {
			return "FAIL";
		}
	}
	private String ticketOrderCallBack(HttpServletResponse response, PrePay prePay) {
		TicketOrder order=ticketOrderService.getById(prePay.getOrderId());
		if (order.getStatus()>TicketOrder.status_create) {
			return "SUCESS";
		}
		if (prepayIds.add(prePay.getId())) {
			order.setPayTime(new Date());
			order.setStatus(TicketOrder.status_payed);
			ticketOrderService.update(order);
			ShopSeller shopSeller=sellerService.getById(order.getSellerId());
			sellerService.update(order.getSellerId(), "soldCount", null==shopSeller.getSoldCount()?1:shopSeller.getSoldCount()+1);
			//分佣
			//incomeRecordService.startIncomeTicket(order.getId());
			orderSellService.saveRecord(order, prePay);
			prepayIds.remove(prePay.getId());
			prePay.setStatus(PrePay.status_success);
			PrePayService.update(prePay);
			
			return "SUCESS";
		}else {
			return "FAIL";
		}
	}
	@RequestMapping("/paySuccess")
	public ModelAndView paySuccess(@RequestParam String prepayNo,Model model,
			HttpServletRequest request, HttpServletResponse response) {
		PrePay pay=PrePayService.getByField("prepayNo", prepayNo);
		switch (pay.getOrderType()) {
		case PRO_ORDER:
			Order order=OrderService.getById(pay.getOrderId());
			if (null!=order) {
				WXOrderSucDto dto=new WXOrderSucDto();
				dto.setOrderId(pay.getOrderId());
				dto.setInfo1("订单支付成功！");
				dto.setInfo2("您的包裹整装待发~");
				dto.setPayAmount(NUM.DF_00.format(order.getTotalMoney()/100d));
				dto.setName(order.getName());
				dto.setMobile(StringUtils.isEmpty(order.getMobile())?"":order.getMobile().substring(0, 3)+"****"+order.getMobile().substring(7, order.getMobile().length()));
				dto.setAddress(order.getAddress());
				dto.setUrl("/wx/order/orderDetail?orderId="+pay.getOrderId());
				model.addAttribute("order", dto);
			}
			break;
		case TICKET_ORDER:
			TicketOrder ticketOrder=ticketOrderService.getById(pay.getOrderId());
			if (null!=ticketOrder) {
				WXOrderSucDto dto=new WXOrderSucDto();
				dto.setOrderId(pay.getOrderId());
				dto.setInfo1("预定成功！");
				dto.setInfo2("祝您旅途愉快~~");
				dto.setPayAmount(NUM.DF_00.format(ticketOrder.getTotalMoney()/100d));
				dto.setName(ticketOrder.getName());
				dto.setMobile(SelfStringUtils.mixMobile(ticketOrder.getMobile()));
				dto.setAddress("");
				dto.setUrl("/wx/order/ticketOrderDetail?orderId="+pay.getOrderId());
				model.addAttribute("order", dto);
			}
			break;
		default:
			break;
		}
		
		return new ModelAndView("/trade/PaySuccess");
	}
}
